package tennos;

import static mathUtils.VecMath.*;
import processing.core.*;
import integration.*;

@SuppressWarnings("serial")
public class FakeSolarSystemDemo extends PApplet {

	float graphicsScale = 5;
	int numFlecks = 50;
	float timeStep = 0.1f;
	float stepsPerFrame = 10;
	float state[][];
	float dstate[][];
	Fleck fl[];
	
	FakeSolarSystem sys;
	Euler eul;
	Heun heu;
	Butcher but;
	RungeKutta4 rk4;
	
	public void setup() {
		size(400, 400);
		
		fl = new Fleck[numFlecks];
		
		sys = new FakeSolarSystem();
		float x[] = new float[2];
		float v[] = new float[2];
		for (int i =0; i<numFlecks; ++i) {
			float ang = random(0, 2*PI);
			float r = 0.25f*width/graphicsScale*random(0.25f, 1f);
			float rn32 = (float) 1f/sqrt(r);
			vecUnitByAngle(ang, x);
			vecScale(x, r);
			vecUnitByAngle(ang+PI/2, v);
			vecScale(v, rn32*random(0.7071f, 1.4142f));
			
			Fleck f = new Fleck(this, x[0], x[1],
					v[0], v[1]);
			fl[i] = f;
			sys.addIntegrable(f);
		}
		
		eul = new Euler(sys);
		eul.findSlope();

		heu = new Heun(sys);
		heu.findSlope();
		
		but = new Butcher(sys);
		but.findSlope();

		rk4 = new RungeKutta4(sys);
		rk4.findSlope();
	}		

	void advance(Integrator in) {
		in.finalizeSlope(timeStep);
		in.takeStep(timeStep);
		in.findSlope();
	}
	
	public void draw() {
		
		for (int i = 0; i < stepsPerFrame; ++i) 
			advance(rk4);
		
		translate(width/2, height/2);
		scale(graphicsScale, -graphicsScale);
		background(0);
		
		stroke(255);
		strokeWeight(0);
		fill(255);
		ellipse(0f, 0f, 1f, 1f);
		
		stroke(255);
		strokeWeight(0);
		noFill();
		for (Fleck f : fl) f.draw();
		
		println(sys.energy());

	}
}
